package com.skivingcloud.report.bigscreen.service.impl;

import com.skivingcloud.common.utils.DateUtils;
import com.skivingcloud.report.bigscreen.entity.ChartDto;
import com.skivingcloud.report.bigscreen.entity.ReportDashboard;
import com.skivingcloud.report.bigscreen.entity.ReportDashboardWidget;
import com.skivingcloud.report.bigscreen.entity.ReportDashboardWidgetDto;
import com.skivingcloud.report.bigscreen.entity.ReportDashboardWidgetValueDto;
import com.skivingcloud.report.bigscreen.mapper.ReportDashboardMapper;
import com.skivingcloud.report.bigscreen.mapper.ReportDashboardWidgetMapper;
import com.skivingcloud.report.bigscreen.service.IReportDashboardService;
import com.skivingcloud.report.datas.entity.OriginalDataDto;
import com.skivingcloud.report.datas.service.IReportDatasetService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 报表看板 服务实现类
 * </p>
 *
 * @author skivingcloud
 * @since 2022-07-29
 */
@Service
public class ReportDashboardServiceImpl extends ServiceImpl<ReportDashboardMapper, ReportDashboard> implements IReportDashboardService {

	@Autowired
	private ReportDashboardWidgetMapper reportDashboardWidgetMapper;
	@Autowired
	private IReportDatasetService reportDatasetService;
	
	@Override
	public ReportDashboard selectById(String reportCode) {
		QueryWrapper<ReportDashboard> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("report_code", reportCode);
        ReportDashboard reportDashboard = this.baseMapper.selectOne(queryWrapper);
		List<ReportDashboardWidgetDto> list = reportDashboardWidgetMapper.selectList(
			new QueryWrapper<ReportDashboardWidget>().lambda().eq(ReportDashboardWidget::getReportCode, reportCode)
					.orderByAsc(ReportDashboardWidget::getSort)
		).stream().map( w -> {
			ReportDashboardWidgetDto dto = new ReportDashboardWidgetDto();
			ReportDashboardWidgetValueDto vDto = new ReportDashboardWidgetValueDto();
			vDto.setCollapse(w.getCollapse());
			vDto.setData(w.getData());
			vDto.setDeleteFlag(w.getDeleteFlag());
			vDto.setEnableFlag(w.getEnableFlag());
			vDto.setOptions(w.getOptions());
			vDto.setPosition(w.getPosition());
			vDto.setRefreshSeconds(w.getRefreshSeconds());
			vDto.setReportCode(w.getReportCode());
			vDto.setSetup(w.getSetup());
			vDto.setSort(w.getSort());
			dto.setType(w.getType());
			dto.setOptions(w.getOptions());
			dto.setValue(vDto);
			return dto;
		}).collect(Collectors.toList());
		reportDashboard.settWidgets(list);
		return reportDashboard;
	}

	@Override
	public List<JsonNode> getChartData(ChartDto dto) throws Exception {
		OriginalDataDto result = reportDatasetService.getDatasetOriginal(dto);
		List<JsonNode> data = result.getData();
        //处理时间轴
        List<JsonNode> resultData = buildTimeLine(data, dto);
        return resultData;
	}

	public List<JsonNode> buildTimeLine(List<JsonNode> data, ChartDto dto) {
        Map<String, String> chartProperties = dto.getChartProperties();
        if (null == chartProperties || chartProperties.size() < 1) {
            return data;
        }
        Map<String, Object> contextData = dto.getContextData();
        if (null == contextData || contextData.size() < 1) {
            return data;
        }
        if (contextData.containsKey("startTime") && contextData.containsKey("endTime")) {
            dto.setStartTime(contextData.get("startTime").toString());
            dto.setEndTime(contextData.get("endTime").toString());
        }
        if (StringUtils.isBlank(dto.getStartTime()) || StringUtils.isBlank(dto.getEndTime())) {
            return data;
        }
        //获取时间轴字段和解析时间颗粒度

        for (Map.Entry<String, String> entry : chartProperties.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            dto.setParticles(value);
            setTimeLineFormat(dto);
            if (StringUtils.isNotBlank(dto.getDataTimeFormat())) {
                dto.setTimeLineFiled(key);
                break;
            }

        }


        if (StringUtils.isBlank(dto.getDataTimeFormat())) {
            return data;
        }

        Date beginTime = DateUtils.stringToDate(dto.getStartTime(), DateUtils.DATE_TIME_PATTERN);
        Date endTime = DateUtils.stringToDate(dto.getEndTime(), DateUtils.DATE_TIME_PATTERN);
        SimpleDateFormat showFormat = new SimpleDateFormat(dto.getTimeLineFormat());
        SimpleDateFormat dataFormat = new SimpleDateFormat(dto.getDataTimeFormat());


        Calendar calendar = Calendar.getInstance();
        calendar.setTime(beginTime);

        Calendar calendarEnd = Calendar.getInstance();
        calendarEnd.setTime(endTime);

        List<String> timeLine = new ArrayList<>();
        List<String> dataTimeline = new ArrayList<>();
        timeLine.add(showFormat.format(calendar.getTime()));
        dataTimeline.add(dataFormat.format(calendar.getTime()));

        //添加时间轴数据
        while (true) {
            calendar.add(dto.getTimeUnit(), 1);
            timeLine.add(showFormat.format(calendar.getTime()));
            dataTimeline.add(dataFormat.format(calendar.getTime()));
            if (showFormat.format(calendar.getTime()).equals(showFormat.format(calendarEnd.getTime()))) {
                break;
            }
        }

        //根据时间轴生成对应的时间线，数据不存在，补数据
        List<JsonNode> result = new ArrayList<>();
        JsonNode jsonDemo = data.get(0);
        String timeLineFiled = dto.getTimeLineFiled();
        for (String dateFormat : dataTimeline) {
            boolean flag = true;
            for (JsonNode datum : data) {
                if (datum.has(timeLineFiled) && datum.get(timeLineFiled).asText().equals(dateFormat)) {
                    result.add(datum);
                    flag = false;
                }
            }
            if (flag) {
                //补数据
                ObjectNode json = new ObjectMapper().createObjectNode();
                jsonDemo.forEach(action -> {
                    if (action.has(timeLineFiled)) {
                        json.put(timeLineFiled, dateFormat);
                    } else {
                        json.put(timeLineFiled, 0);
                    }
                });
                result.add(json);
            }

        }
        return result;
    }

    //设置时间格式
    private void setTimeLineFormat(ChartDto dto) {
        String particles = dto.getParticles();
        if ("xAxis-hour".equals(particles)) {
            dto.setDataTimeFormat("yyyy-MM-dd HH");
            dto.setTimeLineFormat("MM-dd HH");
            dto.setTimeUnit(Calendar.HOUR);
        } else if ("xAxis-day".equals(particles)) {
            dto.setDataTimeFormat("yyyy-MM-dd");
            dto.setTimeLineFormat("yyyy-MM-dd");
            dto.setTimeUnit(Calendar.DATE);
        } else if ("xAxis-month".equals(particles)) {
            dto.setDataTimeFormat("yyyy-MM");
            dto.setTimeLineFormat("yyyy-MM");
            dto.setTimeUnit(Calendar.MONTH);
        } else if ("xAxis-year".equals(particles)) {
            dto.setDataTimeFormat("yyyy");
            dto.setTimeLineFormat("yyyy");
            dto.setTimeUnit(Calendar.YEAR);
        }
    }
}
